#pragma once
#include "KeyDefinitions.h"

namespace Core{
	class ScriptManager;
}

namespace Graphics{
	class GUIManager;
}

namespace Input{
	struct KeyData{
		KeyData():isPressed(false),wasPressed(false){}

		bool isPressed;
		bool wasPressed;
	};

	struct MouseData{
		MouseData():xPos(0),yPos(0),zPos(0),deltaX(0),deltaY(0),deltaZ(0){}

		unsigned int 	xPos,
						yPos,
						zPos;
		long 	deltaX,
				deltaY,
				deltaZ;
	};

	class InputInitParams{
	public:
		virtual ~InputInitParams(){}
	};

	class InputSystem{
	public:
		InputSystem();
		virtual ~InputSystem() {}

		virtual void initialize(boost::shared_ptr<InputInitParams> inputParams) = 0;
		virtual void update() = 0;

		bool									getSync() { return m_synced; }
		bool 									keyIsPressed(KeyDefinition key);
		bool 									keyWasPressed(KeyDefinition key);
		std::pair<float,float>					getMouseDeltaMovement();
		std::pair<unsigned int,unsigned int> 	getMousePosition();
		int 									getMouseWheelMovement();
		void									setMouseSensitivity(float sens) { m_mouseSensitivity = sens; }

		void registerGUIManager(boost::shared_ptr<Graphics::GUIManager> mgr);
		void unregisterGUIManager(boost::shared_ptr<Graphics::GUIManager> mgr);
		void synchronizeInput();
	protected:
		// Lua wrappers
		bool keyPressed_luaWrap(int keyId);

		MouseData						m_mouseDataFront,
										m_mouseDataBack;
		MouseData						*m_mouseDataFrontPtr,
										*m_mouseDataBackPtr;

		bool							m_synced;
		float							m_mouseSensitivity;

		std::map<KeyDefinition,KeyData> m_keyMapFront,
										m_keyMapBack;
		std::map<KeyDefinition,KeyData> *m_keyMapFrontPtr,
										*m_keyMapBackPtr;

		boost::shared_ptr<ThreadLib::Mutex> m_bufferSwapMutex,
											m_guiMgrMutex;

		std::set<boost::shared_ptr<Graphics::GUIManager>> m_GUIManagers;

		friend class Core::ScriptManager;
	};	
}

typedef boost::shared_ptr<Input::InputSystem> InputSystemPtr;